package scuts.core.lifting;
import scuts.core.types.ProgressiveFuture;

import scuts.core.types.Option;
using scuts.core.types.Option;

class LiftWithOption1 
{

  public static function liftWithOption <A, B> (f:A->B):Option<A>->Option<B> 
  {
    return function (a:Option<A>) {
      return switch (a) {
        case Some(v): Some(f(v));
        case None:    None;
      }
    }
  }

}
class LiftWithOption2 
{

  public static function liftWithOption <A, B, C> (f:A->B->C):Option<A>->Option<B>->Option<C>
  {
    return function (a:Option<A>, b:Option<B>) {
      return switch (a) {
        case Some(v1): 
          switch (b) {
            case Some(v2): Some(f(v1,v2));
            case None :    None;
          }
        case None: None;
      }
    }
  }

}
class LiftWithOption3
{

  /**
   * Turns a pure function with 3 parameters into a monadic function operating on Options.
   */
  public static function liftWithOption <A, B, C, D> (f:A->B->C->D):Option<A>->Option<B>->Option<C>->Option<D>
  {
    return function (a:Option<A>, b:Option<B>, c:Option<C>) {
      return switch (a) {
        case Some(v1): 
          switch (b) {
            case Some(v2): 
              switch (c) {
                case Some(v3): Some(f(v1, v2, v3));
                case None:     None;
              }
            case None : None;
          }
        case None: None;
      }
    }
  }

}

class LiftWithOption4
{

  /**
   * Turns a pure function with 3 parameters into a monadic function operating on Options.
   */
  public static function liftWithOption <A, B, C, D, E> (f:A->B->C->D->E):Option<A>->Option<B>->Option<C>->Option<D>->Option<E>
  {
    return function (a:Option<A>, b:Option<B>, c:Option<C>, d:Option<D>) {
      return switch (a) {
        case Some(v1): 
          switch (b) {
            case Some(v2): 
              switch (c) {
                case Some(v3):
                  switch (d) {
                    case Some(v4): Some(f(v1, v2, v3, v4));
                    case None:     None;
                  }
                case None: None;
              }
            case None : None;
          }
        case None: None;
      }
    }
  }

}